"""
MCP API端点

提供MCP功能的RESTful API接口
"""

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List, Optional

from app.database import get_db
from app.models.user import User
from app.api.v1.endpoints.auth import get_current_user
from app.schemas.mcp import (
    MCPSessionCreate,
    MCPSessionResponse,
    MCPRequestPayload,
    MCPResponsePayload,
    MCPContextResponse
)
from app.services.mcp_client_service import MCPClientService
from app.services.mcp_context_service import MCPContextService
from app.core.logging_config import app_logger
from app.core.config import settings

router = APIRouter(prefix="/mcp", tags=["MCP"])


@router.post("/sessions", response_model=MCPSessionResponse, status_code=status.HTTP_201_CREATED)
async def create_mcp_session(
    session_data: MCPSessionCreate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    创建MCP会话
    
    功能：
    1. 创建新的MCP会话
    2. 建立与MCP服务器的WebSocket连接
    3. 初始化上下文
    
    参数：
    - mcp_server_url: MCP服务器地址（可选，使用默认配置）
    - conversation_id: 关联的对话ID（可选）
    - model_config_id: 关联的模型配置ID（可选）
    - initial_context: 初始上下文数据（可选）
    
    返回：
    - session_id: 会话ID
    - status: 会话状态
    - created_at: 创建时间
    """
    try:
        service = MCPClientService(db=db, user_id=current_user.id)
        
        session = await service.create_session(
            mcp_server_url=session_data.mcp_server_url,
            conversation_id=session_data.conversation_id,
            model_config_id=session_data.model_config_id,
            initial_context=session_data.initial_context,
            connection_config=session_data.connection_config
        )
        
        app_logger.info(f"用户{current_user.id}创建MCP会话: {session.session_id}")
        
        return MCPSessionResponse.model_validate(session)
        
    except Exception as e:
        app_logger.error(f"创建MCP会话失败: {str(e)}", exc_info=e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"创建MCP会话失败: {str(e)}"
        )


@router.get("/sessions", response_model=List[MCPSessionResponse])
async def get_mcp_sessions(
    is_active: Optional[bool] = None,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    获取用户的MCP会话列表
    
    参数：
    - is_active: 是否只返回活跃会话（可选）
    
    返回：
    - 会话列表
    """
    try:
        service = MCPClientService(db=db, user_id=current_user.id)
        sessions = await service.get_user_sessions(is_active=is_active)
        
        return [MCPSessionResponse.model_validate(s) for s in sessions]
        
    except Exception as e:
        app_logger.error(f"获取MCP会话列表失败: {str(e)}", exc_info=e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取会话列表失败: {str(e)}"
        )


@router.get("/sessions/{session_id}", response_model=MCPSessionResponse)
async def get_mcp_session(
    session_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    获取MCP会话详情
    
    参数：
    - session_id: 会话ID
    
    返回：
    - 会话详情
    """
    try:
        service = MCPClientService(db=db, user_id=current_user.id)
        session = await service.get_session(session_id=session_id)
        
        if not session:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="会话不存在"
            )
        
        # 验证权限
        if session.user_id != current_user.id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权访问此会话"
            )
        
        return MCPSessionResponse.model_validate(session)
        
    except HTTPException:
        raise
    except Exception as e:
        app_logger.error(f"获取MCP会话失败: {str(e)}", exc_info=e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取会话失败: {str(e)}"
        )


@router.post("/sessions/{session_id}/request", response_model=MCPResponsePayload)
async def send_mcp_request(
    session_id: str,
    request_data: MCPRequestPayload,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    发送MCP请求
    
    功能：
    1. 验证会话有效性
    2. 发送REQUEST消息到MCP服务器
    3. 等待RESPONSE响应
    4. 更新上下文（如果需要）
    
    参数：
    - session_id: 会话ID
    - payload: 请求负载数据
    - update_context: 是否更新上下文（默认True）
    - timeout: 超时时间（秒，可选）
    
    返回：
    - response: 响应数据
    - context_updated: 上下文是否已更新
    - message_id: 消息ID
    """
    try:
        service = MCPClientService(db=db, user_id=current_user.id)
        
        # 验证会话权限
        session = await service.get_session(session_id=session_id)
        if not session or session.user_id != current_user.id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权访问此会话"
            )
        
        # 发送请求
        response = await service.send_request(
            session_id=session_id,
            payload=request_data.payload,
            update_context=request_data.update_context,
            timeout=request_data.timeout
        )
        
        app_logger.info(f"用户{current_user.id}发送MCP请求: session_id={session_id}")
        
        return MCPResponsePayload(**response)
        
    except HTTPException:
        raise
    except Exception as e:
        app_logger.error(f"发送MCP请求失败: {str(e)}", exc_info=e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"发送请求失败: {str(e)}"
        )


@router.delete("/sessions/{session_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_mcp_session(
    session_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    关闭并删除MCP会话
    
    功能：
    1. 断开WebSocket连接
    2. 删除会话记录
    3. 清理相关上下文（可选保留）
    
    参数：
    - session_id: 会话ID
    """
    try:
        service = MCPClientService(db=db, user_id=current_user.id)
        
        # 验证会话权限
        session = await service.get_session(session_id=session_id)
        if not session or session.user_id != current_user.id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权访问此会话"
            )
        
        # 删除会话
        await service.delete_session(session_id=session_id)
        
        app_logger.info(f"用户{current_user.id}删除MCP会话: session_id={session_id}")
        
        return None
        
    except HTTPException:
        raise
    except Exception as e:
        app_logger.error(f"删除MCP会话失败: {str(e)}", exc_info=e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"删除会话失败: {str(e)}"
        )


@router.get("/sessions/{session_id}/contexts", response_model=List[MCPContextResponse])
async def get_session_contexts(
    session_id: str,
    context_type: Optional[str] = None,
    limit: int = 50,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    获取会话的上下文列表
    
    参数：
    - session_id: 会话ID
    - context_type: 上下文类型过滤（可选）
    - limit: 返回数量限制（默认50）
    
    返回：
    - 上下文列表
    """
    try:
        # 验证会话权限
        service = MCPClientService(db=db, user_id=current_user.id)
        session = await service.get_session(session_id=session_id)
        if not session or session.user_id != current_user.id:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权访问此会话"
            )
        
        # 获取上下文
        context_service = MCPContextService(db=db)
        contexts = await context_service.get_session_contexts(
            session_id=session_id,
            context_type=context_type,
            limit=limit
        )
        
        return [MCPContextResponse.model_validate(c) for c in contexts]
        
    except HTTPException:
        raise
    except Exception as e:
        app_logger.error(f"获取会话上下文失败: {str(e)}", exc_info=e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取上下文失败: {str(e)}"
        )


@router.get("/health")
async def mcp_health_check():
    """
    MCP功能健康检查
    
    返回：
    - status: 健康状态
    - timestamp: 时间戳
    - mcp_enabled: MCP功能是否启用
    """
    from datetime import datetime
    return {
        "status": "healthy",
        "timestamp": datetime.utcnow().isoformat(),
        "mcp_enabled": True,
        "server_url": settings.mcp_server_url
    }


@router.get("/debug")
async def mcp_debug_info(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    MCP调试信息接口
    
    用于诊断MCP相关的问题
    """
    try:
        from sqlalchemy import inspect
        inspector = inspect(db.bind)
        tables = inspector.get_table_names()
        
        # 检查MCP相关表是否存在
        mcp_tables = [table for table in tables if table.startswith('mcp_')]
        
        # 检查用户表是否存在
        user_table_exists = 'users' in tables
        
        return {
            "user_id": current_user.id,
            "all_tables": tables,
            "mcp_tables": mcp_tables,
            "user_table_exists": user_table_exists,
            "mcp_sessions_exists": 'mcp_sessions' in tables,
            "mcp_messages_exists": 'mcp_messages' in tables,
            "mcp_contexts_exists": 'mcp_contexts' in tables
        }
        
    except Exception as e:
        app_logger.error(f"MCP调试信息获取失败: {str(e)}", exc_info=e)
        return {
            "error": str(e),
            "user_id": current_user.id
        }


@router.post("/test-connection")
async def test_mcp_connection(
    test_data: dict,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    测试MCP服务器连接
    
    功能：
    1. 测试与指定MCP服务器的连接
    2. 验证服务器是否可达
    3. 检查连接配置是否正确
    
    参数：
    - server_url: MCP服务器地址（可选，使用默认配置）
    - connection_config: 连接配置（可选）
    
    返回：
    - success: 连接是否成功
    - response_time: 响应时间（毫秒）
    - message: 连接结果消息
    - server_url: 测试的服务器地址
    """
    try:
        from app.core.mcp.client import MCPClient
        import time
        
        # 获取测试的服务器地址
        server_url = test_data.get('server_url', settings.mcp_server_url)
        connection_config = test_data.get('connection_config', {})
        
        if not server_url:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="MCP服务器地址不能为空"
            )
        
        # 验证URL格式
        if not (server_url.startswith('ws://') or server_url.startswith('wss://')):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="MCP服务器地址必须以 ws:// 或 wss:// 开头"
            )
        
        # 检查服务器是否可达（基本连通性测试）
        try:
            import socket
            from urllib.parse import urlparse
            
            parsed_url = urlparse(server_url)
            host = parsed_url.hostname
            port = parsed_url.port or (443 if parsed_url.scheme == 'wss' else 80)
            
            # 简单的TCP连接测试
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(5)
            result = sock.connect_ex((host, port))
            sock.close()
            
            if result != 0:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=f"无法连接到服务器 {host}:{port}，请检查服务器是否正在运行"
                )
        except Exception as e:
            app_logger.warning(f"服务器连通性检查失败: {str(e)}")
        
        app_logger.info(f"用户{current_user.id}开始测试MCP连接: {server_url}")
        
        # 创建临时MCP客户端进行连接测试
        start_time = time.time()
        
        try:
            # 创建MCP客户端实例
            client = MCPClient(
                server_url=server_url,
                timeout=connection_config.get('timeout', 10),  # 测试连接使用较短超时
                max_retries=1,  # 测试时只重试1次
                heartbeat_interval=connection_config.get('heartbeat_interval', 30)
            )
            
            # 尝试连接
            connected = await client.connect()
            
            if connected:
                # 连接成功，立即断开
                await client.disconnect()
                response_time = int((time.time() - start_time) * 1000)
                
                app_logger.info(f"用户{current_user.id}MCP连接测试成功: {server_url}, 响应时间: {response_time}ms")
                
                return {
                    "success": True,
                    "response_time": response_time,
                    "message": f"MCP服务器连接成功 (响应时间: {response_time}ms)",
                    "server_url": server_url
                }
            else:
                response_time = int((time.time() - start_time) * 1000)
                app_logger.warning(f"用户{current_user.id}MCP连接测试失败: {server_url}")
                
                return {
                    "success": False,
                    "response_time": response_time,
                    "message": "无法连接到MCP服务器",
                    "server_url": server_url
                }
                
        except Exception as conn_error:
            response_time = int((time.time() - start_time) * 1000)
            error_msg = str(conn_error)
            
            # 改进错误消息处理
            if "1011" in error_msg:
                error_msg = "WebSocket服务器内部错误 (1011)，可能是服务器不支持MCP协议或配置错误"
            elif "10061" in error_msg:
                error_msg = "连接被拒绝，请检查服务器是否正在运行且支持MCP协议"
            elif "timeout" in error_msg.lower():
                error_msg = "连接超时，请检查服务器地址和网络连接"
            
            app_logger.error(f"用户{current_user.id}MCP连接测试异常: {server_url}, 错误: {error_msg}")
            
            return {
                "success": False,
                "response_time": response_time,
                "message": f"连接测试失败: {error_msg}",
                "server_url": server_url
            }
        
    except HTTPException:
        raise
    except Exception as e:
        app_logger.error(f"MCP连接测试失败: {str(e)}", exc_info=e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"连接测试失败: {str(e)}"
        )


@router.get("/stats")
async def get_mcp_stats(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    获取MCP会话统计信息
    
    返回：
    - total_sessions: 总会话数
    - active_sessions: 活跃会话数
    - total_messages: 总消息数
    - total_errors: 总错误数
    """
    try:
        app_logger.info(f"开始获取用户{current_user.id}的MCP统计信息")
        
        # 先检查表是否存在
        from sqlalchemy import inspect
        inspector = inspect(db.bind)
        tables = inspector.get_table_names()
        app_logger.info(f"数据库中的表: {tables}")
        
        if 'mcp_sessions' not in tables:
            app_logger.warning("mcp_sessions表不存在，返回默认统计信息")
            return {
                "total_sessions": 0,
                "active_sessions": 0,
                "total_messages": 0,
                "total_errors": 0
            }
        
        # 直接使用数据库查询，避免复杂的服务初始化
        from app.models.mcp_session import MCPSession
        from app.models.mcp_message import MCPMessage, MessageStatus
        
        # 获取用户的会话统计
        app_logger.info("获取会话统计...")
        try:
            total_sessions = db.query(MCPSession).filter(MCPSession.user_id == current_user.id).count()
            app_logger.info(f"总会话数: {total_sessions}")
        except Exception as e:
            app_logger.error(f"获取总会话数失败: {str(e)}")
            total_sessions = 0
        
        try:
            active_sessions = db.query(MCPSession).filter(
                MCPSession.user_id == current_user.id,
                MCPSession.is_active == True
            ).count()
            app_logger.info(f"活跃会话数: {active_sessions}")
        except Exception as e:
            app_logger.error(f"获取活跃会话数失败: {str(e)}")
            active_sessions = 0
        
        # 获取消息和错误统计
        app_logger.info("获取消息统计...")
        try:
            if 'mcp_messages' in tables:
                total_messages = db.query(MCPMessage).join(MCPSession).filter(
                    MCPSession.user_id == current_user.id
                ).count()
                app_logger.info(f"总消息数: {total_messages}")
            else:
                app_logger.warning("mcp_messages表不存在")
                total_messages = 0
        except Exception as e:
            app_logger.error(f"获取总消息数失败: {str(e)}")
            total_messages = 0
        
        try:
            if 'mcp_messages' in tables:
                total_errors = db.query(MCPMessage).join(MCPSession).filter(
                    MCPSession.user_id == current_user.id,
                    MCPMessage.status == MessageStatus.ERROR
                ).count()
                app_logger.info(f"错误消息数: {total_errors}")
            else:
                total_errors = 0
        except Exception as e:
            app_logger.error(f"获取错误消息数失败: {str(e)}")
            total_errors = 0
        
        app_logger.info(f"MCP统计信息获取成功: 总会话={total_sessions}, 活跃会话={active_sessions}, 消息={total_messages}, 错误={total_errors}")
        
        return {
            "total_sessions": total_sessions,
            "active_sessions": active_sessions,
            "total_messages": total_messages,
            "total_errors": total_errors
        }
        
    except Exception as e:
        app_logger.error(f"获取MCP统计信息失败: {str(e)}", exc_info=e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取统计信息失败: {str(e)}"
        )